home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / metkit / lfnames.c < prev    next >
C/C++ Source or Header  |  1997-06-07  |  10KB  |  333 lines

  1. #ifdef _MSC_VER
  2.     #pragma warning (disable: 4001 4115 4135 4305 4759)   
  3. #endif
  4.  
  5. // listing 2, lfnames.c
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <dos.h>
  9. #include <io.h>
  10. #include <fcntl.h>
  11. #include <sys\stat.h>
  12. #include <string.h>
  13. #include <errno.h>
  14.  
  15. #include "lfnames.h"
  16.  
  17. // #define TEST  // defines main to make test program
  18.  
  19. #ifdef _MSC_VER
  20. #if (_MSC_VER>=600)
  21. #define SREGS _SREGS
  22. #define REGS  _REGS
  23. #define intdosx _intdosx
  24. #undef FP_OFF
  25. #undef FP_SEG
  26. // need to do this for MSC, because the MSC version requires
  27. // an Lvalue for the pointer!
  28. #define FP_OFF(p) (unsigned short)(p)
  29. #define FP_SEG(p) (unsigned short)((unsigned long)(void __far *)(p)>>16)
  30. #endif
  31. #endif
  32.  
  33. static int DoDosCall( unsigned func, union REGS *r, struct SREGS *s )
  34. // helper function to call DOS interrupt
  35. {
  36.    r->x.ax = func;
  37.    intdosx(r,r,s);
  38.    if(r->x.cflag)
  39.       _doserrno = r->x.ax;
  40.    else
  41.       _doserrno = 0;
  42.    return r->x.cflag;
  43. }
  44.  
  45. #define SETPTR(seg,off,ptr) s.seg = FP_SEG((ptr)), r.x.off = FP_OFF((ptr))
  46.  
  47. int lfn_api( const char *rootname )
  48. // returns non-zero if volume supports long file names
  49. {
  50.    union REGS r; struct SREGS s;
  51.    char filesystem[40];
  52.    SETPTR(es,di,filesystem);
  53.    r.x.cx = sizeof(filesystem);
  54.    SETPTR(ds,dx,rootname);
  55.    if(DoDosCall(0x71a0,&r,&s))
  56.       return 0;
  57.    return r.x.bx & 0x4000;  // check for FS_LFN_APIS flag
  58. }
  59.  
  60. unsigned GetShortPathName( const char *filename,
  61.               const char *shortname, unsigned size )
  62. {
  63.    union REGS r; struct SREGS s;
  64.    if(size<SFN_MAX_PATH)  // path too small?
  65.       return 0;
  66.    SETPTR(ds,si,filename);
  67.    SETPTR(es,di,shortname);
  68.    r.x.cx = 1;
  69.    if(DoDosCall(0x7160,&r,&s))
  70.       return 0;
  71.    return strlen(shortname);
  72. }
  73.  
  74. unsigned GetLongPathName( const char *filename,
  75.               const char *longname, unsigned size )
  76. {
  77.    union REGS r; struct SREGS s;
  78.    if(size<LFN_MAX_PATH)  // path too small?
  79.       return 0;
  80.    SETPTR(ds,si,filename);
  81.    SETPTR(es,di,longname);
  82.    r.x.cx = 2;
  83.    if(DoDosCall(0x7160,&r,&s))
  84.       return 0;
  85.    return strlen(longname);
  86. }
  87.  
  88. int lfn_mkdir( const char *path )
  89. {
  90.    union REGS r; struct SREGS s;
  91.    SETPTR(ds,dx,path);
  92.    if(DoDosCall(0x7139,&r,&s))
  93.      return -1;
  94.    return 0;
  95. }
  96.  
  97. int lfn_rmdir( const char *path )
  98. {
  99.    union REGS r; struct SREGS s;
  100.    SETPTR(ds,dx,path);
  101.    if(DoDosCall(0x713a,&r,&s))
  102.      return -1;
  103.    return 0;
  104. }
  105.  
  106. int lfn_chdir( const char *path )
  107. {
  108.    union REGS r; struct SREGS s;
  109.    SETPTR(ds,dx,path);
  110.    if(DoDosCall(0x713b,&r,&s))
  111.       return -1;
  112.    return 0;
  113. }
  114.  
  115. int lfn_unlink( const char *path )
  116. {
  117.    union REGS r; struct SREGS s;
  118.    SETPTR(ds,dx,path);
  119.    r.h.cl = _A_ARCH|_A_SYSTEM|_A_RDONLY;
  120.    r.h.ch = 0; // must match
  121.    r.x.si = 0; // no wild cards
  122.    if(DoDosCall(0x7141,&r,&s))
  123.      return -1;
  124.    return 0;
  125. }
  126.  
  127. int lfn_rename( const char *oldname, const char *newname )
  128. {
  129.    union REGS r; struct SREGS s;
  130.    SETPTR(ds,dx,oldname);
  131.    SETPTR(es,di,newname);
  132.    if(DoDosCall(0x7156,&r,&s))
  133.       return -1;
  134.    return 0;
  135. }
  136.  
  137. int lfn_access( const char *path, int amode )
  138. {
  139.    union REGS r; struct SREGS s;
  140.    r.x.bx = 0;       // get extended attributes
  141.    SETPTR(ds,dx,path);
  142.    if(DoDosCall(0x7143,&r,&s))
  143.       return -1;
  144.    if(!(amode&0x02) || !(r.x.cx & _A_RDONLY) )
  145.       return 0;
  146.    errno = EACCES;
  147.    return -1;
  148. }
  149.  
  150. typedef unsigned long DWORD;
  151.  
  152. typedef struct _FILETIME {
  153.    DWORD dwLowDateTime;
  154.    DWORD dwHighDateTime;
  155. } FILETIME;
  156.  
  157. typedef struct _WIN32_FIND_DATA { // wfd
  158.    DWORD dwFileAttributes;
  159.    FILETIME ftCreationTime;
  160.    FILETIME ftLastAccessTime;
  161.    FILETIME ftLastWriteTime;
  162.    DWORD    nFileSizeHigh;
  163.    DWORD    nFileSizeLow;
  164.    DWORD    dwReserved0;
  165.    DWORD    dwReserved1;
  166.    char     cFileName[ LFN_MAX_PATH ];
  167.    char    cAlternateFileName[ 14 ];
  168. } WIN32_FIND_DATA;
  169.  
  170. int lfn_findfirst( const char *path, int attrib, struct lfn_find_t *finfo )
  171. {
  172.    WIN32_FIND_DATA finddata;
  173.    union REGS r; struct SREGS s;
  174.    SETPTR(ds,dx,path);
  175.    SETPTR(es,di,&finddata);
  176.    r.x.cx = attrib;
  177.    r.x.si = 1; // MS-DOS format time/date
  178.    if(DoDosCall(0x714e,&r,&s))
  179.       return -1;
  180.    finfo->findhandle = r.x.ax;  // save find handle
  181.    strcpy(finfo->name,finddata.cFileName);
  182.    finfo->size = finddata.nFileSizeLow;
  183.    finfo->wr_date =
  184.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime >> 16 );
  185.    finfo->wr_time =
  186.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime & 0xffff );
  187.    finfo->attrib = finddata.dwFileAttributes & 0x7f;
  188.    return 0;
  189. }
  190.  
  191. int lfn_findnext( struct lfn_find_t *finfo )
  192. {
  193.    WIN32_FIND_DATA finddata;
  194.    union REGS r; struct SREGS s;
  195.    SETPTR(es,di,&finddata);
  196.    r.x.si = 1; // use dos time
  197.    r.x.bx = finfo->findhandle;
  198.    if(DoDosCall(0x714f,&r,&s))
  199.       return -1;
  200.    strcpy(finfo->name,finddata.cFileName);
  201.    finfo->size = finddata.nFileSizeLow;
  202.    finfo->wr_date =
  203.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime >> 16);
  204.    finfo->wr_time =
  205.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime & 0xffff );
  206.    finfo->attrib = finddata.dwFileAttributes & 0x7f;
  207.    return 0;
  208. }
  209.  
  210. void lfn_findclose( struct lfn_find_t *finfo )
  211. {
  212.    union REGS r; struct SREGS s;
  213.    r.x.bx = finfo->findhandle;
  214.    DoDosCall(0x71a1,&r,&s);
  215. }
  216.  
  217. int lfn_open( const char *path, int mode, int smode )
  218. {
  219.    union REGS r; struct SREGS s;
  220.    SETPTR(ds,si,path);
  221.    r.x.bx = mode & 0x3; // read/write flags
  222.    if(mode & O_CREAT) {
  223.       switch(smode&(S_IREAD|S_IWRITE)) {
  224.          case 0:
  225.             r.x.bx |= 0x0010; // deny read/write
  226.             break;
  227.          case S_IREAD:
  228.             r.x.bx |= 0x0020; // deny write
  229.             break;
  230.          case S_IWRITE:
  231.             r.x.bx |= 0x0030; // deny read
  232.             break;
  233.          case S_IWRITE|S_IREAD:
  234.             r.x.bx |= 0x0040; // deny none
  235.             break;
  236.       }
  237.    }
  238.    r.x.cx = _A_NORMAL;
  239.    r.x.dx = 0;
  240.    if(mode & O_CREAT ) r.x.dx |= 0x0010;
  241.    if(mode & O_TRUNC ) r.x.dx |= 0x0002;
  242.    if(mode & O_EXCL ) r.x.dx |= 0x0001;  // file must exist
  243.    if(DoDosCall(0x716c,&r,&s))
  244.       return -1;
  245.    return r.x.ax;  // return file handle
  246. }
  247.  
  248. FILE *lfn_fopen( const char *filename, const char *mode )
  249. {
  250.    char shortname[LFN_MAX_PATH];
  251.    if( strchr(mode,'a') || strchr(mode,'w') ) {
  252.       // if the file doesn't exist - create it
  253.       if( lfn_access(filename,00) ) {
  254.          int hf = lfn_open(filename,O_CREAT|O_TRUNC|O_WRONLY,0);
  255.          close(hf);
  256.       }
  257.    } // convert a long name to a short name, if needed
  258.    GetShortPathName(filename,shortname,sizeof(shortname));
  259.    return fopen(shortname,mode);
  260. }
  261.  
  262. #ifdef TEST
  263. int main( int argc, char **argv )
  264. {
  265.    if(argc>2) {
  266.       if( strcmpi(argv[1],"api")==0 ) {
  267.          printf("Long filenames are %savailable for \"%s\".\n",
  268.             lfn_api(argv[2])?"":"not ",argv[2]);
  269.       } else if( strcmpi(argv[1],"shortname")==0 ) {
  270.          char buf[SFN_MAX_PATH];
  271.          if( GetShortPathName(argv[2],buf,sizeof(buf)) ) {
  272.             printf("The short name of %s is %s.\n",argv[2],buf);
  273.             {
  274.                int i;
  275.                for(i=0;i<strlen(buf);i++)
  276.                   printf("'%c' %02x ",buf[i],buf[i]);
  277.             }
  278.          } else
  279.             printf("Unable to convert to %s to a short name.\n",
  280.                argv[2]);
  281.       } else if( strcmpi(argv[1],"longname")==0 ) {
  282.          char buf[LFN_MAX_PATH];
  283.          if( GetLongPathName(argv[2],buf,sizeof(buf)) )
  284.             printf("The long name of \"%s\" is \"%s\".\n",argv[2],buf);
  285.          else
  286.             printf("Unable to convert to \"%s\" to a long name.\n",
  287.                argv[2]);
  288.       } else if( strcmpi(argv[1],"mkdir")==0) {
  289.          if( lfn_mkdir(argv[2]) )
  290.             printf("dos error %d\n",_doserrno);
  291.       } else if( strcmpi(argv[1],"chdir")==0) {
  292.          if( lfn_chdir(argv[2]) )
  293.             printf("dos error %d\n",_doserrno);
  294.       } else if( strcmpi(argv[1],"rmdir")==0) {
  295.          if( lfn_rmdir(argv[2]) )
  296.             printf("dos error %d\n",_doserrno);
  297.       } else if( strcmpi(argv[1],"ex